package com.wbp.cms.client.result ;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

 
public class Result<T> {
    /**
     * @since 1.0.0
     */
    private boolean success = true;
    /**
     * 错误码
     *
     * @since 1.0.0
     */
    private int errCode =BaseResultCode.SUCCESS.getErrCode();

    /**
     * 错误详细信息
     *
     * @since 1.0.0
     */
    private String errMsg;

    /**
     * 如果返回分页结果，用于承载满足条件的纪录总数
     *
     * @since 1.0.0
     */
    private int total;
    /**
     * @since 1.0.0
     */
    private T data;

    private Map<String, Object> extra;

    private ResultCode resultCode;
     
    public Map<String, Object> getExtra() {
        return extra;
    }

    public Result<T> setExtra(Map<String, Object> extra) {
        this.extra = extra;
        return this;
    }

    public Result<T> addExtra(String key, Object v) {
        if (extra == null) {
            extra = new HashMap<String, Object>();
        }
        extra.put(key, v);
        return this;
    }

    /**
     * @since 1.0.0
     */
    public Result(boolean success) {
        this.success = success;
    }

    /**
     * @since 1.0.0
     */
    public boolean isSuccess() {
        return success;
    }
    
	public boolean isFailed() {
		return !success;
	}

    /**
     * @since 1.0.0
     */
    public int getErrCode() {
        return errCode;
    }

    /**
     * @since 1.0.0
     */
    public String getErrMsg() {
        return errMsg;
    }

    /**
     * @since 1.0.0
     */
    public int getTotal() {
        return total;
    }

    /**
     * @return 如果返回分页结果，返回第一条纪录
     * @since 1.0.0
     */
    public T getData() {
        if (!success) {
            return null;
        }
        return data;
    }

    public ResultCode getResultCode() {
        if (isFailed() && resultCode == null) {
            return BaseResultCode.SYS_ERROR;
        }
        return resultCode;
    }

    /**
     * 构建一个失败的返回
     *
     * @param errMsg 错误信息
     * @param <T>    成功返回时关联的数据类型
     * @return 构建出的失败返回对象
     * @since 1.0.0
     */
    public static <T> Result<T> buildError(String errMsg) {
    	Result<T> resultDO = new Result<T>(false);
        resultDO.errCode = BaseResultCode.SYS_ERROR.getErrCode();
        resultDO.errMsg = errMsg;
        return resultDO;
    }

    /**
     * 构建一个失败的返回
     *
     * @param errCode 错误代码
     * @param errMsg  错误信息
     * @param <T>     成功返回时关联的数据类型
     * @return 构建出的失败返回对象
     * @since 1.0.0
     */
    public static <T> Result<T> buildError(int errCode, String errMsg) {
    	Result<T> resultDO = new Result<T>(false);
        resultDO.errCode = errCode;
        resultDO.errMsg = errMsg;
        return resultDO;
    }

    public static <T> Result<T> buildError(ResultCode resultCode) {
    	Result<T> resultDO = new Result<T>(false);
        resultDO.setErrCode(resultCode.getErrCode());

        //将tip放到errMsg上是为了兼容
        resultDO.setErrMsg(StringUtils.isNotBlank(resultCode.getErrTip()) ? resultCode.getErrTip() : resultCode.getErrMsg());
        resultDO.resultCode = resultCode;
        return resultDO;
    }

    public static <T> Result<T> buildError(Result<?> another) {
    	Result<T> resultDO = new Result<T>(false);
        resultDO.resultCode = another.resultCode;
        resultDO.errCode = another.errCode;
        resultDO.errMsg = another.errMsg;

        return resultDO;
    }

    public Result<T> setErr(ResultCode resultCode) {
        setErrCode(resultCode.getErrCode());
        //将tip放到errMsg上是为了兼容
        setErrMsg(StringUtils.isNotBlank(resultCode.getErrTip()) ? resultCode.getErrTip() : resultCode.getErrMsg());
        this.resultCode = resultCode;
        return this;
    }

    /**
     * 构建一个成功的返回：结果为单个对象，可通过 {@link #getData()} 提取
     *
     * @param data 结果对象
     * @param <T>  结果对象的数据类型
     * @return 构建出的成功返回对象
     * @since 1.0.0
     */
    public static <T> Result<T> buildSuccess(T data) {
    	Result<T> resultDO = new Result<T>(true);
        resultDO.data = data;
        return resultDO;
    }

    public Result<T> setData(T data) {
        this.data = data;
        return this;
    }

    /**
     * 构建一个成功的返回：结果为分页查询结果，
     * 可通过 {@link #getTotal()} 提取满足条件的纪录总数
     *
     * @param total 满足条件的纪录总数
     * @param data  分页结果对象
     * @param <T>   结果对象的数据类型
     * @return 构建出的成功返回对象
     * @since 1.0.0
     */
    public static <T> Result<T> buildSuccess(int total, T data) {
    	Result<T> resultDO = new Result<T>(true);
        resultDO.total = total;
        resultDO.data = data;
        return resultDO;
    }

    public Result<T> setErrCode(int errCode) {
        this.errCode = errCode;
        return this;
    }

    public Result<T> setErrMsg(String errMsg) {
        this.errMsg = errMsg;
        return this;
    }

    /**
     * @since 1.0.0
     */
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
